package org.contextsensitivetodo.context.updater;

import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.contextsensitivetodo.context.ContextDelivery;
import org.contextsensitivetodo.context.UserContext;
import org.contextsensitivetodo.context.configuration.UserContextConfiguration;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

/**
 * This class is responsible for updating context information.
 * 
 * @author juhani
 * 
 */
public class ContextUpdaterEngineService extends Service implements LocationListener {

	private static final long INTERVAL = 1000 * 60 * 15;

	private Timer timer = new Timer();

	private LocationManager locationManager;

	@Override
	public void onCreate() {
		super.onCreate();

		this.startContextUpdaterEngine();
	}



	public void startContextUpdaterEngine() {

		Log.d("cstodo", "Starting context update engine");

		Log.d("cstodo", "Adding location listener for locations");


		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000, 10, this);
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 6000, 10, this);


		Log.d("cstodo", "Scheduling fixed rate update");
		timer.scheduleAtFixedRate(new TimerTask() {

			@Override
			public void run() {

				forceFirstLocationUpdate();

				List<UserContext> contexes = UserContextConfiguration.getInstance().getAllContext();
				Log.d("cstodo", "Context state update trigered for "+contexes.size()+" contexes. Contexes: " +contexes);

				Iterator<UserContext> iterator = contexes.iterator();
				while (iterator.hasNext()) {
					UserContext userContext = (UserContext) iterator.next();
					Log.d("cstodo", "going to update context: "+userContext);
					userContext.doStateUpdate();
					Log.d("cstodo", "updated. Has more: " + iterator.hasNext());
				}


			}
		}, 0, INTERVAL);
	}

	public void stopContextUpdaterEngine() {
		if (this.timer != null) {
			this.timer.cancel();
		}
		if(this.locationManager != null){
			this.locationManager.removeUpdates(this);
		}
		this.stopSelf();
	}


	/**
	 * fake location change event to update location firt time
	 */
	private void forceFirstLocationUpdate(){

		Location lastKnownNetworkLocation = ContextDelivery.getInstace()
		.getLocationManager().getLastKnownLocation(
				LocationManager.NETWORK_PROVIDER);
		Location lastKnownGPSLocation = ContextDelivery.getInstace()
		.getLocationManager().getLastKnownLocation(
				LocationManager.GPS_PROVIDER);

		if(lastKnownGPSLocation != null){
			if(lastKnownNetworkLocation != null && lastKnownNetworkLocation.getTime() > lastKnownGPSLocation.getTime()){
				onLocationChanged(lastKnownNetworkLocation);
			}else{
				onLocationChanged(lastKnownGPSLocation);
			}
			
		}else if(lastKnownNetworkLocation != null){
			onLocationChanged(lastKnownNetworkLocation);
		}

	}



	@Override
	public void onDestroy() {
		this.stopContextUpdaterEngine();
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}





	public void onLocationChanged(Location location) {
		List<UserContext> contexes = UserContextConfiguration.getInstance().getAllContext();
		Log.d("cstodo", "Context state update trigered with location for "+contexes.size()+" contexes. Contexes: " +contexes);

		Iterator<UserContext> iterator = contexes.iterator();
		while (iterator.hasNext()) {
			UserContext userContext = (UserContext) iterator.next();
			Log.d("cstodo", "going to update context with location: "+userContext);
			userContext.doStateUpdate(location);
			Log.d("cstodo", "updated  with location. Has more: " + iterator.hasNext());
		}
	}

	public void onProviderDisabled(String provider) {}
	public void onProviderEnabled(String provider) {}
	public void onStatusChanged(String provider, int status, Bundle extras) {}

}
